package fiuba.algo3.tp2;

import java.util.ArrayList;
import java.util.Iterator;


public class Mapa {

	private static Mapa instance = null;
	private Hectarea[][] coordenadas;
	private ArrayList <Zona> zonas; 
	private ArrayList <Coordenada> edificablesHaReparar;

	protected Mapa() {
		
		this.coordenadas = new Hectarea[12][12];
		for (int i = 0; i < 10; i++) {
			for (int j = 0; j < 12; j++) {
				this.coordenadas[i][j] = new Hectarea("llano");
			}
		}
		for (int i = 10; i < 12; i++) {
			for (int j = 0; j < 12; j++) {
				this.coordenadas[i][j] = new Hectarea("agua");
			}
		}
		
		this.zonas = new ArrayList<Zona>();
		this.edificablesHaReparar = new ArrayList<Coordenada>();
	}

	public static Mapa getInstance() {
		if (instance == null) {
			instance = new Mapa();
		}
		return instance;
	}

	public int devolverTamanio() {
		return this.coordenadas.length;
	}

	
	public void agregarEdificable(Coordenada coordenada, Edificable edificable) throws SueloInadecuadoException {
		
		this.obtenerHectarea(coordenada).agregarEdificable(edificable);

	}

	public ArrayList<Zona> getZonas() {
		return zonas;
	}

	public ArrayList<Coordenada> getEdificablesHaReparar() {
		return edificablesHaReparar;
	}
	
	public Edificable obtenerEdificable(Coordenada coordenada) {

		Edificable edificable = this.obtenerHectarea(coordenada).obtenerEdificable();
		return edificable;
	}

	public boolean llegaElAgua(Coordenada coordenada) {

		return true;

	}

	public Hectarea obtenerHectarea(Coordenada coordenada) {

		return this.coordenadas[coordenada.obtenerFila()][coordenada.obtenerColumna()];
	}

	public Hectarea coordenada(int fila, int columna) {
		return this.coordenadas[fila][columna];
	}

	public void reparar(Coordenada coordenada) {

		this.obtenerHectarea(coordenada).reparar();
	}

	public int obtenerDistancia(Coordenada coordenadaIndustria,
			Coordenada coordenadaResidencia) {
		// TODO Auto-generated method stub
		return 0;
	}

	public void agregarCentral(Coordenada coordenada, CentralElectrica central) throws SueloInadecuadoException {

		this.obtenerHectarea(coordenada).agregarCentral(central);
		int radio = central.obtenerRadioDeAlcance();
		this.proporcionarEnergia(coordenada, radio, central);
	}

	private void proporcionarEnergia(Coordenada coordenadaCentro,
		int radioCirculo, CentralElectrica central) {

		
		 /* VER COMO RECORRER EL RADIO
		
		int fila = coordenadaCentro.obtenerFila(); int columna =
		coordenadaCentro.obtenerColumna();
		  
		System.out.println(fila); System.out.println(columna);
		 
		for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { Hectarea
		hectareaActual = this.coordenada(fila + i, columna + j);
		hectareaActual.suministrarEnergia(); } }
		  
		/* for (int i = -4; i<radio+1; i++){ for (int j=-1; j<radio-1; j++){
		 Hectarea hectareaActual = this.coordenada(fila + i, columna + j);
		 System.out.println(fila + i); System.out.println(columna + j);
		 hectareaActual.suministrarEnergia(); } }
		*/

		int diametroCirculo = transformaEnDiametro(radioCirculo);

		int contador = 1;
		for (int i = 0; i < diametroCirculo; i++) {
			for (int j = 0; j < diametroCirculo; j++) {

				if ((i <= (diametroCirculo) / 2) & (j >= ((diametroCirculo) / 2 - i) & (j <= ((diametroCirculo) / 2 + i)))) {
					if (((coordenadaCentro.obtenerColumna() - diametroCirculo / 2) + i >= 0)
							& ((coordenadaCentro.obtenerFila() - diametroCirculo / 2) + j >= 0)
							& ((coordenadaCentro.obtenerColumna() - diametroCirculo / 2) + i < this.devolverTamanio())
							& ((coordenadaCentro.obtenerFila() - diametroCirculo / 2) + j < this.devolverTamanio())) {
						(coordenadas[(coordenadaCentro.obtenerFila() - diametroCirculo / 2) + j][(coordenadaCentro.obtenerColumna() - diametroCirculo / 2) + i]).suministrarEnergia();;
					}

				} else { // Para desde la mitad hacia abajo

					int restaParaSimetria = (2 * contador);
					if (j >= ((diametroCirculo) / 2 - (i - restaParaSimetria)) & (j <= ((diametroCirculo) / 2 + (i - restaParaSimetria)))) {
						if (((coordenadaCentro.obtenerColumna() - diametroCirculo / 2) + i >= 0)
								& ((coordenadaCentro.obtenerFila() - diametroCirculo / 2) + j >= 0)
								& ((coordenadaCentro.obtenerColumna() - diametroCirculo / 2) + i < this.devolverTamanio())
								& ((coordenadaCentro.obtenerFila() - diametroCirculo / 2) + j < this.devolverTamanio())) {
							(coordenadas[(coordenadaCentro.obtenerFila() - diametroCirculo / 2) + j][(coordenadaCentro.obtenerColumna() - diametroCirculo / 2) + i]).suministrarEnergia();;
						}
					}
				}
			}
			if ((i > (diametroCirculo) / 2)) {
				contador += 1;
			}
		}
	}
	
	public int transformaEnDiametro(int numero) {
		   return ((numero*2)-1);
   }


	public ArrayList devolverServicios(Coordenada coordenada) {
		ArrayList servicios = this.obtenerHectarea(coordenada).obtenerServicios();
		return servicios;
	}

	public void agregarPozoDeAgua(Coordenada coordenada, PozoDeAgua pozo) throws SueloInadecuadoException {
		this.obtenerHectarea(coordenada).agregarPozo(pozo);
	}

	public void agregarTuberia(Coordenada coordenada) {
		this.obtenerHectarea(coordenada).agregarTuberia(coordenada);
	}

	public void agregarLineaDeTension(Coordenada coordenada) throws SueloInadecuadoException {
		this.obtenerHectarea(coordenada).agregarLineaDeTension(coordenada);

	}

	public void agregarCalle(Coordenada coordenada) throws SueloInadecuadoException {
		this.obtenerHectarea(coordenada).agregarCalle(coordenada);
		
	}

	public boolean hayConexionConLineaDeTension(Coordenada coordenada) {
		
		boolean hayConexion = false;
		
		Hectarea hectareaActual = this.obtenerHectarea(coordenada);
		ArrayList hectareasAdyacentes = this.obtenerHectareasAdyacentes(coordenada);
		
		Iterator it = hectareasAdyacentes.iterator();
		while(it.hasNext()){
			Hectarea hectareaAdyacente = (Hectarea)it.next();
			if (hectareaAdyacente.tieneElectricidad() || hectareaAdyacente.tieneCentral()){
				hayConexion = true;
			}
		}

		return hayConexion;

	}
	
	public boolean hayConexionConTuberia(Coordenada coordenada) {
		
		boolean hayConexion = false;
		
		Hectarea hectareaActual = this.obtenerHectarea(coordenada);
		ArrayList<Hectarea> hectareasAdyacentes = this.obtenerHectareasAdyacentes(coordenada);
		
		Iterator<Hectarea> it = hectareasAdyacentes.iterator();
		while(it.hasNext()){
			Hectarea hectareaAdyacente = it.next();
			if (hectareaAdyacente.tieneAgua() || hectareaAdyacente.tienePozoDeAgua()){
				hayConexion = true;
			}
		}
		
		return hayConexion;
	}

	private ArrayList obtenerHectareasAdyacentes(Coordenada coordenada) {
		ArrayList<Hectarea> hectareasAdyacentes = new ArrayList();
		
		int fila = coordenada.obtenerFila();
		int columna = coordenada.obtenerColumna();
		
		Hectarea hectarea1 = this.coordenada(fila + 1, columna);
		hectareasAdyacentes.add(hectarea1);
		Hectarea hectarea2 = this.coordenada(fila - 1, columna);
		hectareasAdyacentes.add(hectarea2);
		Hectarea hectarea3 = this.coordenada(fila, columna + 1);
		hectareasAdyacentes.add(hectarea3);
		Hectarea hectarea4 = this.coordenada(fila, columna - 1);
		hectareasAdyacentes.add(hectarea4);
			
		return hectareasAdyacentes;
	}

	public void agregarZona(Zona unaZona) {
		this.zonas.add(unaZona);
	}

	
	public void agregarEdificableHaReparar(Coordenada unaCoordenada) {
		this.edificablesHaReparar.add(unaCoordenada);
	}

	public Hectarea[][] getMapaCoordenado() {
		return this.coordenadas;
	}
	
	public void terminarTurno() {
		
		
	}

}
